﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TransCode.Entitys;
using TransCode.Logic;
using System.Threading;
using TransCodeTask;
using System.IO;
using System.Xml.Linq;

namespace TransCodeService
{
    public class JobWorker
    {
        private string SourceFilePath = ConfigValue.GetConfigByName("SourceFilePath");

        private string TargetFilePath = ConfigValue.GetConfigByName("TargetFilePath");

        private string TempFilePath = ConfigValue.GetConfigByName("TempFilePath");

        private int Count = Int32.Parse(ConfigValue.GetConfigByName("Count"));

        private List<Thread> _threads = new List<Thread>();

        private List<List<Target>> dicTarget = new List<List<Target>>();

        private List<JobIndex> jobIndexs = new List<JobIndex>();

        JobLogic jobdb;

        VideoLogic videodb;

        private int tempCount = -1;

        public JobWorker(JobLogic jobdb)
        {
            this.jobdb = jobdb;
            videodb = new VideoLogic();
        }

        public void running(object obj)
        {
            tempCount = Count;
            Job job = obj as Job;
            //eyxz.avi
            string file = job.Filename;
            string filename = file.Substring(0, file.IndexOf('.'));
            string tempDir = TempFilePath + "\\" + filename + "\\";
            string targetPath = TargetFilePath + "\\" + filename + "\\";
            Video video = new Video();
            video.VideoName = "Complent" + filename + ".avi";
            job.State = 1;
            jobdb.Save(job);
            bool Tran = false;
            TranscodeTask transtask = new TranscodeTask();
            FFTask fftask = new FFTask();
            fftask.task = job.TaskList.FirstOrDefault(it => it.Type == 1);
            if (fftask.TaskTranAVI(file, SourceFilePath, tempDir))
                Tran = true;
            else
            {
                fftask.Dispose();
                transtask.task = job.TaskList.FirstOrDefault(it => it.Type == 1);
                if (transtask.TaskRunning(file, SourceFilePath, tempDir))
                    Tran = true;
                else
                    transtask.Dispose();
            }
            if (Tran)
            {
                int time = fftask.TaskGetAVITime(file, tempDir);
                int step = time % tempCount == 0 ? time / tempCount : time / Count + 1;
                for (int i = 0; i < tempCount; i++)
                {
                    if (step * (i + 1) > time)
                    {
                        tempCount = i;
                        break;
                    }
                    if (!fftask.TaskCutAVI(filename + ".avi", tempDir, DateTime.MinValue.AddSeconds(step * i).ToString("HH:mm:ss"), DateTime.MinValue.AddSeconds(step * (i + 1)).ToString("HH:mm:ss"), i))
                    {
                        fftask.Dispose();
                        break;
                    }
                    Thread _thread = new Thread(new ParameterizedThreadStart(Worker));
                    JobIndex indexjob = new JobIndex();
                    indexjob.index = i;
                    indexjob.job = job;
                    indexjob.video = video;
                    indexjob._thread = _thread;
                    indexjob.IsComplent = false;
                    _thread.Start(indexjob);
                    jobIndexs.Add(indexjob);
                    _threads.Add(_thread);
                }
                while (_threads.Count > 0)
                {
                    Thread.Sleep(60000);
                }

                int AddTime = 0;
                string path = "";
                var jobComplent = jobIndexs.Where(it => it.IsComplent == false);
                if (jobComplent == null || jobComplent.Count() == 0)
                    return;
                for (int i = 0; i < tempCount; i++)
                {
                    if (i == 0)
                        path = fftask.TaskMergeAVI(filename, tempDir + filename + i + "\\Complent" + filename + i + ".avi", tempDir + filename + (i + 1) + "\\Complent" + filename + (i + 1) + ".avi", tempDir, i);
                    else if (i + 1 < tempCount)
                        path = fftask.TaskMergeAVI(filename, path, tempDir + filename + (i + 1) + "\\Complent" + filename + (i + 1) + ".avi", tempDir, i);
                    int temp = fftask.TaskGetAVITime(filename + i + ".avi", tempDir + filename + i + "\\");
                    AddTime += temp;
                    TargetTask target = new TargetTask();
                    target.FrameDictionaryBuilder(filename + i + ".avi", tempDir);
                    target.TargetInfoBuilder(filename + i + ".avi", tempDir, targetPath, AddTime);
                    video.TargetList.AddRange(target.TargetInfoList);
                    dicTarget.Insert(i, target.TargetInfoList);
                }
                File.Move(path, targetPath + video.VideoName);
                video.LocationPath = targetPath;
                videodb.Save(video);
                Thread _threadFeature = new Thread(new ParameterizedThreadStart(FeatureWorker));
                JobIndex jobFeature = new JobIndex();
                jobFeature.index = tempCount;
                jobFeature.job = job;
                jobFeature.video = video;
                jobFeature._thread = _threadFeature;
                jobFeature.IsComplent = false;
                _threadFeature.Start(jobFeature);
            }
            else
            {
                job.State = -1;
                jobdb.Save(job);
                transtask.Dispose();
            }
        }

        public void Worker(object obj)
        {
            JobIndex jobIndex = obj as JobIndex;
            Job job = jobIndex.job;
            Video video = jobIndex.video;
            int i = jobIndex.index;

            string file = job.Filename;
            string filename = file.Substring(0, file.IndexOf('.'));
            string tempDir = TempFilePath + "\\" + filename + "\\";

            ObjectdetectorTask objectdetectortask = new ObjectdetectorTask();
            objectdetectortask.task = job.TaskList.FirstOrDefault(it => it.Type == 2);
            if (objectdetectortask.TaskRunning(filename + i + ".avi", tempDir))
            {
                CutframeTask cutframeTask = new CutframeTask();
                cutframeTask.task = job.TaskList.FirstOrDefault(it => it.Type == 3);
                if (cutframeTask.TaskRunning(filename + i + ".avi", tempDir))
                {
                    FFTask fftask = new FFTask();
                    fftask.task = job.TaskList.FirstOrDefault(it => it.Type == 4);
                    if (fftask.TaskRunning(filename + i + ".avi", tempDir))
                    {
                        job.State = 2;
                        jobdb.Save(job);
                        jobIndex.IsComplent = true;
                    }
                    else
                    {
                        job.State = -1;
                        jobdb.Save(job);
                        fftask.Dispose();
                    }
                }
                else
                {
                    job.State = -1;
                    jobdb.Save(job);
                    cutframeTask.Dispose();
                }
            }
            else
            {
                job.State = -1;
                jobdb.Save(job);
                objectdetectortask.Dispose();
            }
            _threads.Remove(jobIndex._thread);
        }


        public void FeatureWorker(object obj)
        {
            JobIndex jobIndex = obj as JobIndex;
            Job job = jobIndex.job;
            Video video = jobIndex.video;
            int cout = jobIndex.index;
            for (int i = 0; i < cout; i++)
            {
                Thread _threadFeature = new Thread(new ParameterizedThreadStart(FeatureWorker));
                JobIndex jobFeature = new JobIndex();
                jobFeature.index = i;
                jobFeature.job = job;
                jobFeature.video = video;
                jobFeature._thread = _threadFeature;
                jobFeature.IsComplent = false;
                _threadFeature.Start(jobFeature);
                _threads.Add(_threadFeature);
            }
        }

        public void GetFeature(object obj)
        {
            JobIndex jobIndex = obj as JobIndex;
            Job job = jobIndex.job;
            Video video = jobIndex.video;
            int current = jobIndex.index;

            string file = job.Filename;
            string filename = file.Substring(0, file.IndexOf('.'));
            string tempDir = TempFilePath + "\\" + filename + "\\";

            FeatureTask featureTask = new FeatureTask();
            if (featureTask.TaskRunning(filename + current + ".avi", tempDir))
            {
                string filePath = tempDir + filename + current + ".avi.xml";
                XElement doc = XElement.Load(filePath);
                int ObjectNumber = int.Parse(doc.Descendants("ObjectNumber").FirstOrDefault().Value);
                for (int i = 1; i <= ObjectNumber; i++)
                {
                    string imagePath = new DirectoryInfo(SourceFilePath + i.ToString()).GetFiles().First().FullName;
                    //File.Move(imagePath + "1.jpg", targetPath);
                }
            }
        }

        public class JobIndex
        {
            public Job job { get; set; }
            public int index { get; set; }
            public Thread _thread { get; set; }
            public Video video { get; set; }
            public bool IsComplent { get; set; }
        }
    }
}
